<template>
  <div id="mapView" class="map-view">
    <!-- 图层控制面板 -->
    <div class="layer-control-panel">
      <el-card class="layer-card">
        <el-collapse v-model="activeCollapse">
          <el-collapse-item title="图层显示控制" name="layers">
            <el-space direction="vertical" alignment="stretch" size="small">
              <el-checkbox v-model="layerVisibility.building"
                @change="toggleLayerVisibility('building')">建筑物</el-checkbox>
              <el-checkbox v-model="layerVisibility.facilities"
                @change="toggleLayerVisibility('facilities')">设施</el-checkbox>
              <el-checkbox v-model="layerVisibility.roads" @change="toggleLayerVisibility('roads')">道路</el-checkbox>
            </el-space>
          </el-collapse-item>
          <el-collapse-item title="距离测量" name="distanceMeasurement">
            <el-space direction="vertical" alignment="stretch" size="small">
              <el-button type="primary" @click="startMeasurement" :disabled="measurementActive">
                <el-icon>
                  <Aim />
                </el-icon>
                开始测量
              </el-button>
              <el-button type="danger" @click="clearMeasurement" :disabled="!measurementActive">
                <el-icon>
                  <Delete />
                </el-icon>
                清除测量
              </el-button>
              <div v-if="measurementResult" class="measurement-result">
                <p>距离: {{ measurementResult.toFixed(2) }} 米</p>
              </div>
              <div v-if="measurementActive && !measurementResult" class="measurement-tip">
                <p>请在地图上点击选择第一个点</p>
              </div>
              <div v-if="measurementActive && firstPoint && !secondPoint" class="measurement-tip">
                <p>请在地图上点击选择第二个点</p>
              </div>
            </el-space>
          </el-collapse-item>
        </el-collapse>
      </el-card>
    </div>

    <!-- 建筑物属性查看对话框 -->
    <el-dialog v-model="buildingInfoVisible" title="建筑物信息" width="500px">
      <div v-if="selectedBuilding">
        <el-descriptions :column="1" border>
          <el-descriptions-item label="建筑名称">{{
            selectedBuilding.attributes.name
          }}</el-descriptions-item>
          <el-descriptions-item label="建筑类型">{{
            selectedBuilding.attributes.Buildingtype
          }}</el-descriptions-item>
          <el-descriptions-item label="描述">{{
            selectedBuilding.attributes.description
          }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="buildingInfoVisible = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 设施属性查看对话框 -->
    <el-dialog v-model="facilityInfoVisible" title="设施信息" width="500px">
      <div v-if="selectedFacility">
        <el-descriptions :column="1" border>
          <el-descriptions-item label="设施名称">{{
            selectedFacility.attributes.name
          }}</el-descriptions-item>
          <el-descriptions-item label="设施类型">{{
            selectedFacility.attributes.FacilitiesType
          }}</el-descriptions-item>
          <el-descriptions-item label="描述">{{
            selectedFacility.attributes.description
          }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="facilityInfoVisible = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 道路属性查看对话框 -->
    <el-dialog v-model="roadInfoVisible" title="道路信息" width="500px">
      <div v-if="selectedRoad">
        <el-descriptions :column="1" border>
          <el-descriptions-item label="道路名称">{{
            selectedRoad.attributes.name
          }}</el-descriptions-item>
          <el-descriptions-item label="道路类型">{{
            selectedRoad.attributes.RoadType
          }}</el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="roadInfoVisible = false">关闭</el-button>
        </span>
      </template>
    </el-dialog>

    <!-- 距离测量结果对话框 -->
    <el-dialog v-model="measurementDialogVisible" title="距离测量结果" width="500px">
      <div v-if="measurementResult">
        <el-descriptions :column="1" border>
          <el-descriptions-item label="起点">
            {{ firstPointInfo ? firstPointInfo.name : '未知点' }}
          </el-descriptions-item>
          <el-descriptions-item label="终点">
            {{ secondPointInfo ? secondPointInfo.name : '未知点' }}
          </el-descriptions-item>
          <el-descriptions-item label="距离">
            {{ measurementResult.toFixed(2) }} 米
          </el-descriptions-item>
        </el-descriptions>
      </div>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="measurementDialogVisible = false">关闭</el-button>
          <el-button type="primary" @click="clearMeasurement">清除测量</el-button>
        </span>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import { nextTick, onMounted, onUnmounted, ref, reactive } from 'vue'
import { ElMessage } from 'element-plus'
import { Aim, Delete } from '@element-plus/icons-vue'
import Map from '@arcgis/core/Map.js'
import MapView from '@arcgis/core/views/MapView.js'
import FeatureLayer from '@arcgis/core/layers/FeatureLayer.js'
import Graphic from '@arcgis/core/Graphic.js'
import Point from '@arcgis/core/geometry/Point.js'
import Polyline from '@arcgis/core/geometry/Polyline.js'
import SimpleMarkerSymbol from '@arcgis/core/symbols/SimpleMarkerSymbol.js'
import SimpleLineSymbol from '@arcgis/core/symbols/SimpleLineSymbol.js'
import TextSymbol from '@arcgis/core/symbols/TextSymbol.js'
import  * as geometryEngine from '@arcgis/core/geometry/geometryEngine.js'
import gaodeLayer from '@/utils/GaoDeBaseLayer'

let view: MapView | null = null
let buildingLayer: FeatureLayer | null = null
let facilitiesLayer: FeatureLayer | null = null
let roadsLayer: FeatureLayer | null = null

// 图层URL
const buildingLayerUrl =
  'https://services8.arcgis.com/CmXfu09loK81if9H/arcgis/rest/services/GISRouteAnalysis/FeatureServer/0'
const facilitiesLayerUrl =
  'https://services8.arcgis.com/CmXfu09loK81if9H/arcgis/rest/services/GISRouteAnalysis/FeatureServer/1'
const roadsLayerUrl =
  'https://services8.arcgis.com/CmXfu09loK81if9H/arcgis/rest/services/GISRouteAnalysis/FeatureServer/2'

// 图层可见性控制
const layerVisibility = ref({
  building: true,
  facilities: true,
  roads: true,
})

// 控制折叠面板的展开状态
const activeCollapse = ref(['layers', 'distanceMeasurement'])

// 查询结果相关
const buildingInfoVisible = ref(false)
const facilityInfoVisible = ref(false)
const roadInfoVisible = ref(false)
let selectedBuilding: Graphic | null = null
let selectedFacility: Graphic | null = null
let selectedRoad: Graphic | null = null

// 距离测量相关
const measurementActive = ref(false)
const measurementResult = ref<number | null>(null)
const measurementDialogVisible = ref(false)
let firstPoint: Point | null = null
let secondPoint: Point | null = null
let firstPointInfo: any = null
let secondPointInfo: any = null
let measurementGraphics: Graphic[] = []

// 切换图层可见性
const toggleLayerVisibility = (layerType: string) => {
  switch (layerType) {
    case 'building':
      if (buildingLayer) {
        buildingLayer.visible = Boolean(layerVisibility.value.building)
      }
      break
    case 'facilities':
      if (facilitiesLayer) {
        facilitiesLayer.visible = Boolean(layerVisibility.value.facilities)
      }
      break
    case 'roads':
      if (roadsLayer) {
        roadsLayer.visible = Boolean(layerVisibility.value.roads)
      }
      break
  }
}

// 开始测量距离
const startMeasurement = () => {
  measurementActive.value = true
  firstPoint = null
  secondPoint = null
  firstPointInfo = null
  secondPointInfo = null
  measurementResult.value = null
  ElMessage.info('请在地图上点击选择第一个点')
}

// 清除测量
const clearMeasurement = () => {
  measurementActive.value = false
  firstPoint = null
  secondPoint = null
  firstPointInfo = null
  secondPointInfo = null
  measurementResult.value = null
  measurementDialogVisible.value = false

  // 清除地图上的测量图形
  if (view) {
    measurementGraphics.forEach(graphic => {
      view!.graphics.remove(graphic)
    })
    measurementGraphics = []
  }
}

// 添加点标记
const addPointMarker = (point: Point, color: string, label: string) => {
  if (!view) return null

  // 创建点标记
  const pointGraphic = new Graphic({
    geometry: point,
    symbol: new SimpleMarkerSymbol({
      color: color,
      outline: {
        color: 'white',
        width: 1
      },
      size: 10
    })
  })

  // 创建文本标签
  const textGraphic = new Graphic({
    geometry: point,
    symbol: new TextSymbol({
      color: 'black',
      haloColor: 'white',
      haloSize: 1,
      text: label,
      yoffset: -20,
      font: {
        size: 12,
        weight: 'bold'
      }
    })
  })

  view.graphics.add(pointGraphic)
  view.graphics.add(textGraphic)
  measurementGraphics.push(pointGraphic)
  measurementGraphics.push(textGraphic)

  return pointGraphic
}

// 添加线标记
const addLineMarker = (point1: Point, point2: Point) => {
  if (!view) return null

  // 创建线几何
  const polyline = new Polyline({
    paths: [[[point1.x, point1.y], [point2.x, point2.y]]],
    spatialReference: view.spatialReference
  })

  // 创建线图形
  const lineGraphic = new Graphic({
    geometry: polyline,
    symbol: new SimpleLineSymbol({
      color: [0, 0, 255, 0.8],
      width: 3,
      style: 'solid'
    })
  })

  // 计算距离
  const distance = geometryEngine.distance(point1, point2, 'meters')

  // 创建距离标签
  const midPoint = new Point({
    x: (point1.x + point2.x) / 2,
    y: (point1.y + point2.y) / 2,
    spatialReference: view.spatialReference
  })

  const distanceText = `${distance.toFixed(2)} 米`
  const textGraphic = new Graphic({
    geometry: midPoint,
    symbol: new TextSymbol({
      color: 'blue',
      haloColor: 'white',
      haloSize: 2,
      text: distanceText,
      font: {
        size: 14,
        weight: 'bold'
      }
    })
  })

  view.graphics.add(lineGraphic)
  view.graphics.add(textGraphic)
  measurementGraphics.push(lineGraphic)
  measurementGraphics.push(textGraphic)

  return distance
}

// 初始化地图
onMounted(() => {
  // 创建建筑物图层 - 使用填充样式
  buildingLayer = new FeatureLayer({
    url: buildingLayerUrl,
    outFields: ['*'],
    visible: layerVisibility.value.building,
    renderer: {
      type: 'simple',
      symbol: {
        type: 'simple-marker',
        color: [255, 165, 0, 0.6], // 橙色半透明
        outline: {
          color: [255, 140, 0, 1], // 深橙色边框
          width: 2
        }
      }
    } as any,
    popupTemplate: {
      title: '建筑物信息',
      content: [
        {
          type: 'fields',
          fieldInfos: [
            { fieldName: 'name', label: '建筑名称' },
            { fieldName: 'BuildingType', label: '建筑类型' },
            { fieldName: 'OBJECTID', label: 'ID' }
          ]
        }
      ]
    }
  })

  // 创建设施图层 - 使用点样式
  facilitiesLayer = new FeatureLayer({
    url: facilitiesLayerUrl,
    outFields: ['*'],
    visible: layerVisibility.value.facilities,
    renderer: {
      type: 'simple',
      symbol: {
        type: 'simple-marker',
        color: [0, 150, 255, 0.8], // 蓝色
        size: 12,
        outline: {
          color: [0, 100, 200, 1], // 深蓝色边框
          width: 2
        },
        style: 'circle'
      }
    } as any,
    popupTemplate: {
      title: '设施信息',
      content: [
        {
          type: 'fields',
          fieldInfos: [
            { fieldName: 'name', label: '设施名称' },
            { fieldName: 'FacilityType', label: '设施类型' },
            { fieldName: 'OBJECTID', label: 'ID' }
          ]
        }
      ]
    }
  })

  // 创建道路图层 - 使用线样式，根据道路类型设置不同颜色
  roadsLayer = new FeatureLayer({
    url: roadsLayerUrl,
    outFields: ['*'],
    visible: layerVisibility.value.roads,
    popupEnabled: false,
    renderer: {
      type: 'unique-value',
      field: 'RoadType',
      defaultSymbol: {
        type: 'simple-line',
        color: [128, 128, 128, 0.8], // 灰色默认
        width: 3
      },
      uniqueValueInfos: [
        {
          value: '主干道',
          symbol: {
            type: 'simple-line',
            color: [255, 0, 0, 0.9], // 红色
            width: 6
          }
        },
        {
          value: '次干道',
          symbol: {
            type: 'simple-line',
            color: [255, 165, 0, 0.8], // 橙色
            width: 4
          }
        },
        {
          value: '支路',
          symbol: {
            type: 'simple-line',
            color: [255, 255, 0, 0.8], // 黄色
            width: 3
          }
        },
        {
          value: '步行道',
          symbol: {
            type: 'simple-line',
            color: [0, 255, 0, 0.8], // 绿色
            width: 2,
            style: 'dash'
          }
        },
        {
          value: '自行车道',
          symbol: {
            type: 'simple-line',
            color: [0, 191, 255, 0.8], // 天蓝色
            width: 2,
            style: 'dot'
          }
        }
      ]
    } as any,
    popupTemplate: {
      title: '道路信息',
      content: [
        {
          type: 'fields',
          fieldInfos: [
            { fieldName: 'name', label: '道路名称' },
            { fieldName: 'RoadType', label: '道路类型' },
            { fieldName: 'OBJECTID', label: 'ID' }
          ]
        }
      ]
    }
  })

  // 创建地图
  const map = new Map({
    basemap: {
      baseLayers: [gaodeLayer],
    },
    layers: [buildingLayer, facilitiesLayer, roadsLayer],
  })

  // 创建地图视图
  view = new MapView({
    container: 'mapView',
    map: map,
    zoom: 16,
    center: [116.79344073176162, 36.53820494873281], // 默认坐标，可修改为学校坐标
  })

  // 添加点击事件监听
  view.on('click', async (event) => {
    // 如果测量模式激活
    if (measurementActive.value) {
      // 获取点击位置的地理坐标
      const point = view!.toMap({ x: event.x, y: event.y })

      // 获取点击位置的屏幕坐标用于查询要素
      const screenPoint = {
        x: event.x,
        y: event.y,
      }

      // 创建查询对象
      const query = view?.hitTest(screenPoint)
      const response = await query

      // 查找点击的要素
      let featureInfo = null
      if (response!.results && response!.results.length > 0) {
        for (const result of response!.results) {
          if ((result as any).graphic && (result as any).graphic.layer) {
            const layer = (result as any).graphic?.layer
            const graphic = (result as any).graphic

            if (layer === buildingLayer || layer === facilitiesLayer || layer === roadsLayer) {
              featureInfo = {
                name: graphic.attributes.name || '未命名要素',
                type: layer === buildingLayer ? '建筑物' :
                      layer === facilitiesLayer ? '设施' : '道路',
                attributes: graphic.attributes
              }
              break
            }
          }
        }
      }

      // 如果是第一个点
      if (!firstPoint) {
        firstPoint = point
        firstPointInfo = featureInfo || { name: '自定义点', type: '未知' }
        addPointMarker(point, 'red', '起点')
        ElMessage.info('请在地图上点击选择第二个点')
      }
      // 如果是第二个点
      else if (!secondPoint) {
        secondPoint = point
        secondPointInfo = featureInfo || { name: '自定义点', type: '未知' }
        addPointMarker(point, 'green', '终点')

        // 添加连接线并计算距离
        const distance = addLineMarker(firstPoint, secondPoint)
        measurementResult.value = distance

        // 显示测量结果对话框
        measurementDialogVisible.value = true
        measurementActive.value = true
      }
      return
    }

    // 非测量模式下的点击处理（查看要素信息）
    const screenPoint = {
      x: event.x,
      y: event.y,
    }

    // 创建查询对象
    const query = view?.hitTest(screenPoint)
    const response = await query

    // 如果没有点击到要素，则返回
    if (!response!.results || response!.results.length === 0) {
      return
    }

    // 遍历结果，查找图层要素
    for (const result of response!.results) {
      if ((result as any).graphic && (result as any).graphic.layer) {
        const layer = (result as any).graphic?.layer
        const graphic = (result as any).graphic

        // 根据图层类型显示不同的信息
        if (layer === buildingLayer) {
          selectedBuilding = graphic
          buildingInfoVisible.value = true
          return
        } else if (layer === facilitiesLayer) {
          selectedFacility = graphic
          facilityInfoVisible.value = true
          return
        } else if (layer === roadsLayer) {
          selectedRoad = graphic
          roadInfoVisible.value = true
          return
        }
      }
    }
  })
})

// 组件卸载时清理资源
onUnmounted(() => {
  if (view) {
    view = null
  }
})
</script>

<style scoped>
.map-view {
  width: 100%;
  height: 100%;
  position: relative;
}

.layer-control-panel {
  position: absolute;
  top: 20px;
  right: 20px;
  z-index: 10;
  width: 280px;
}

.layer-card {
  background-color: rgba(255, 255, 255, 0.9);
  border-radius: 8px;
}

.measurement-result {
  margin-top: 10px;
  padding: 8px;
  background-color: #f0f9ff;
  border-radius: 4px;
  font-weight: bold;
  color: #409eff;
}

.measurement-tip {
  margin-top: 10px;
  padding: 8px;
  background-color: #fff9f0;
  border-radius: 4px;
  color: #e6a23c;
}
</style>
